package com.trip.wechat.platform.web.controller.mp;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.google.common.hash.Hashing;
import com.trip.wechat.platform.datastore.MpAccountStore;
import com.trip.wechat.platform.model.AccountBO;
import com.trip.wechat.platform.model.MessageBO;
import com.trip.wechat.platform.service.MessageService;
import com.trip.wechat.platform.web.dto.SimpleMessageDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.Charset;
import java.util.*;

/**
 * 功能说明: MP 服务器验证回调<br>
 * 系统说明: <br>
 * 模块说明: <br>
 * 功能描述: <br>
 *
 *     /mp/message?signature=e50955426c6973102ec207d2ed8a28346a756ff6&echostr=17340761504315472491&timestamp=1526798432&nonce=1871812136
 */
@RestController
@RequestMapping("/mp")
public class MessageController {

    final Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    XmlMapper xmlMapper = new XmlMapper();

    @Autowired
    MpAccountStore accountStore;
    @Autowired
    MessageService messageService;

    @RequestMapping(value = "/{id}/message", method = {RequestMethod.GET})
    @ResponseBody
    public String validate(@PathVariable("id") String publicKey,
                           @RequestParam("signature") String signature,
                           @RequestParam("echostr") String echostr,
                           @RequestParam("timestamp") String timestamp,
                           @RequestParam("nonce") String nonce) {
        Optional<AccountBO> op = accountStore.get(publicKey);
        if (!op.isPresent()) {
            LOGGER.info("[MessageController.validate] unknown publickey => {}", publicKey);
            return "";
        }
        // 1）将token、timestamp、nonce三个参数进行字典序排序
        List<String> list = new ArrayList<>();
        list.add(op.get().getAppToken());
        list.add(timestamp);
        list.add(nonce);
        Collections.sort(list);
        // 2）将三个参数字符串拼接成一个字符串进行sha1加密
        StringBuffer buffer = new StringBuffer();
        list.stream().forEachOrdered(s -> buffer.append(s));
        String hash1 = Hashing.sha1().hashString(buffer.toString(), Charset.forName("UTF-8")).toString();
        // 开发者获得加密后的字符串可与signature对比
        if (Objects.equals(signature, hash1)) {
            return echostr;
        } else {
            return "";
        }
    }

    @RequestMapping(value = "/{id}/message", method = {RequestMethod.POST})
    @ResponseBody
    public String message(@RequestBody String body, HttpServletRequest request) {
        try {
            SimpleMessageDTO dto = xmlMapper.readValue(body, SimpleMessageDTO.class);

            MessageBO bo = new MessageBO();
            BeanUtils.copyProperties(dto, bo);

            messageService.dispatch(bo);
        } catch (Exception e) {
            LOGGER.warn("[MessageController.message] parse message failed! body => {}", body, e);
        }
        return "";
    }
}
